// 05_structs.rs
// Rust 结构体教程

// 1. 定义结构体
// 使用 struct 关键字定义结构体
#[derive(Debug)]  // 派生 Debug trait 以便打印结构体
struct User {
    username: String,
    email: String,
    sign_in_count: u64,
    active: bool,
}

// 2. 元组结构体
struct Color(i32, i32, i32);  // RGB 颜色
struct Point(i32, i32, i32);  // 三维坐标点

// 3. 类单元结构体（没有字段）
struct AlwaysEqual;

fn main() {
    // 4. 创建结构体实例
    let user1 = User {
        email: String::from("someone@example.com"),
        username: String::from("someusername123"),
        active: true,
        sign_in_count: 1,
    };
    
    // 5. 访问结构体字段
    println!("用户邮箱: {}", user1.email);
    println!("用户名: {}", user1.username);
    
    // 6. 修改可变结构体实例的字段
    let mut user2 = User {
        email: String::from("someone@example.com"),
        username: String::from("someusername123"),
        active: true,
        sign_in_count: 1,
    };
    
    user2.email = String::from("anotheremail@example.com");
    println!("修改后的用户邮箱: {}", user2.email);
    
    // 7. 从其他实例创建实例
    let user3 = User {
        email: String::from("another@example.com"),
        username: String::from("anotherusername567"),
        ..user1  // 剩余字段使用 user1 的值
    };
    println!("user3 的登录次数: {}", user3.sign_in_count);
    
    // 8. 元组结构体实例
    let black = Color(0, 0, 0);
    let origin = Point(0, 0, 0);
    
    println!("黑色: ({}, {}, {})", black.0, black.1, black.2);
    println!("原点: ({}, {}, {})", origin.0, origin.1, origin.2);
    
    // 9. 类单元结构体实例
    let subject = AlwaysEqual;
    
    // 10. 结构体作为函数参数
    let user4 = build_user(
        String::from("user4@example.com"),
        String::from("user4name"),
    );
    println!("构建的用户: {:?}", user4);
    
    // 11. 使用结构体更新语法
    let user5 = User {
        email: String::from("user5@example.com"),
        username: String::from("user5name"),
        ..user4
    };
    println!("更新的用户: {:?}", user5);
    
    // 12. 使用关联函数创建实例
    let user6 = User::new(
        String::from("user6@example.com"),
        String::from("user6name"),
    );
    println!("使用关联函数创建的用户: {:?}", user6);
    
    // 13. 带有方法的结构体
    let rect1 = Rectangle {
        width: 30,
        height: 50,
    };
    
    println!(
        "矩形的面积是 {} 平方像素。",
        rect1.area()
    );
    
    let rect2 = Rectangle {
        width: 10,
        height: 40,
    };
    
    let rect3 = Rectangle {
        width: 60,
        height: 45,
    };
    
    println!("rect1 能容纳 rect2 吗? {}", rect1.can_hold(&rect2));
    println!("rect1 能容纳 rect3 吗? {}", rect1.can_hold(&rect3));
    
    // 14. 关联函数
    let sq = Rectangle::square(3);
    println!("正方形的面积: {}", sq.area());
}

// 10. 结构体作为函数参数
fn build_user(email: String, username: String) -> User {
    User {
        email,      // 字段初始化简写语法
        username,   // 当变量名和字段名相同时
        active: true,
        sign_in_count: 1,
    }
}

// 13. 定义带有方法的结构体
#[derive(Debug)]
struct Rectangle {
    width: u32,
    height: u32,
}

// 为结构体实现方法
impl Rectangle {
    // 方法的第一个参数总是 self，表示调用该方法的结构体实例
    fn area(&self) -> u32 {
        self.width * self.height
    }
    
    // 方法可以有多个参数
    fn can_hold(&self, other: &Rectangle) -> bool {
        self.width > other.width && self.height > other.height
    }
    
    // 关联函数（不是方法，因为它们没有 self 参数）
    fn square(size: u32) -> Rectangle {
        Rectangle {
            width: size,
            height: size,
        }
    }
}

// 为结构体实现关联函数
impl User {
    fn new(email: String, username: String) -> User {
        User {
            email,
            username,
            active: true,
            sign_in_count: 1,
        }
    }
}